
package at.fhj.ase.clientarch.server.sigar;

import java.sql.Timestamp;
import java.util.Timer;
import java.util.TimerTask;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import at.fhj.ase.clientarch.common.HardwareData;
import at.fhj.ase.clientarch.common.exception.AlreadyInitializedException;

/**
 * Class controlling the access on the hardware information interface, provided by Sigar.
 * 
 * @author cja, sfe | www.fh-joanneum.at | Client Architectures and Design
 */
public enum SigarController {
  INSTANCE;

  private final Logger logger = LoggerFactory.getLogger(getClass().getName());
  private final HardwareInfo hwInfo = new HardwareInfo();

  private final long TIMER_START_DELAY_MILLIS = 0;
  private final long TIMER_REPEAT_TIME_MILLIS = 250;
  private Timer runningTimer;

  private class RefreshTimer extends TimerTask {
    @Override
    public void run() {
      setCurrentData(getDataFromHardware());
    }
  }

  /** Property containing always the must current and recently fetched data from hardware. */
  private HardwareData currentData;// = getDataFromHardware(); //init the property with a valid value to prevent nullpointer access on public getter

  public void init() {
    if (runningTimer != null) {
      throw new AlreadyInitializedException("SigarController has already been initialized");
    }
    runningTimer = new Timer(true);
    runningTimer.schedule(new RefreshTimer(), TIMER_START_DELAY_MILLIS, TIMER_REPEAT_TIME_MILLIS);
  }

  public HardwareData getCurrentData() {
    //    logger.debug("RETURN to others: " + currentData);
    return currentData;
  }

  private synchronized void setCurrentData(final HardwareData currentData) {
    this.currentData = currentData;
  }

  private HardwareData getDataFromHardware() {
    final Timestamp currentTime = new Timestamp(System.currentTimeMillis());
    final HardwareData hardwareData = new HardwareData(hwInfo.getCPULoad(), hwInfo.getRAMLoad(), currentTime);

    logger.debug("Get from HW: " + hardwareData);
    return hardwareData;
  }
}
